package org.onvivals.app.mqtt.listener;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.codec.MqttPublishMessage;
import net.dreamlu.iot.mqtt.codec.MqttQoS;
import net.dreamlu.iot.mqtt.core.server.event.IMqttMessageListener;
import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate;
import org.onvivals.app.mqtt.util.PlayUtil;
import org.onvivals.module.iot.entity.IotDevice;
import org.onvivals.module.iot.entity.IotMessageLog;
import org.onvivals.module.iot.service.IIotDeviceService;
import org.onvivals.module.iot.service.IIotMessageLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.tio.core.ChannelContext;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 消息监听器
 *
 * @author wsq
 */
@Service
@Slf4j
public class MqttServerMessageListener implements IMqttMessageListener, SmartInitializingSingleton {
	@Autowired
	private ApplicationContext applicationContext;
	private MqttServerTemplate mqttServerTemplate;

	@Autowired
	private IIotMessageLogService messageLogService;

	@Autowired
	private IIotDeviceService deviceService;

	@Autowired
	@Lazy
	private PlayUtil playUtil;

	@Override
	public void onMessage(ChannelContext context, String clientId, String topic, MqttQoS qos, MqttPublishMessage mqttPublishMessage) {
		log.info("context:{} clientId:{} message:{} payload:{}", context, clientId, mqttPublishMessage, new String(mqttPublishMessage.payload(), StandardCharsets.UTF_8));
		String message = new String(mqttPublishMessage.getPayload(), StandardCharsets.UTF_8);
		log.info("接收消息主题 : {}", topic);
		log.info("接收消息Qos : {}", qos.value());
		log.info("接收消息内容 : {}", message);
		// 提高代码可读性，添加注释，并处理潜在的数组越界问题
		String[] topicItems = topic.substring(1).split("/");
		String deviceNum = topicItems[0];
		String name = topicItems[1];
		// 使用Enum代替String常量优化代码可读性和可维护性
		try {
			switch (name) {
				case "info":
					reportDevice(clientId, deviceNum, message);
					break;
				case "play":
					playVideo(deviceNum, message);
					break;

			}
		} catch (IllegalArgumentException e) {
			log.error("未知的消息类型: {}. {}", name, e.getMessage());
		}
	}

	/**
	 * 播放视频消息。
	 *
	 * @param deviceNum 设备编号，用于标识播放视频的设备。
	 * @param message   包含播放信息的JSON字符串，比如视频索引。
	 */
	public void playVideo(String deviceNum, String message) {
		try {
			// 解析传入的message字符串为JSONObject，获取播放索引
			JSONObject jsonObject = JSONUtil.parseObj(message);
			int index = jsonObject.getInt("index");
			// 根据产品ID、设备编号和索引查询消息日志，获取播放链接和消息ID
			IotMessageLog messageLog = messageLogService.getOne(Wrappers.<IotMessageLog>lambdaQuery().eq(IotMessageLog::getDeviceId, deviceNum).eq(IotMessageLog::getSortNum, index + 1), false);
			if (messageLog != null) {
				// 如果找到有效的消息日志，则播放视频
				playUtil.play(deviceNum, messageLog.getMessageUrl(), messageLog.getMessageId(), messageLog.getSortNum());
			} else {
				// 如果没有找到有效的消息日志，则播放失败，并清除相关的消息日志
				playUtil.play(deviceNum, "", "", -1);
				messageLogService.remove(Wrappers.<IotMessageLog>lambdaQuery().eq(IotMessageLog::getDeviceId, deviceNum));
			}
		} catch (Exception e) {
			log.error("播放异常", e);
		}
	}

	/**
	 * 上报设备信息
	 */
	private void reportDevice(String clientId, String deviceNum, String message) {
		try {
			// 设备实体
			IotDevice deviceEntity = deviceService.selectDeviceBySerialNumber(deviceNum);
			// 上报设备信息
			JSONObject jsonObject = JSONUtil.parseObj(message);
			IotDevice device = JSON.parseObject(message, IotDevice.class);
			device.setUserId(deviceEntity.getUserId());
			device.setUserName(deviceEntity.getUserName());
			device.setSerialNumber(deviceNum);
			device.setFirmwareVersion(Convert.toBigDecimal(jsonObject.get("firmwareVersion")));
			device.setBattery(Convert.toInt(jsonObject.get("battery")));
			deviceService.reportDevice(device, deviceEntity);
		} catch (Exception e) {
			log.error("接收设备信息，解析数据时异常 message={}", e.getMessage());
		}
	}

	@Override
	public void afterSingletonsInstantiated() {
		// 单利 bean 初始化完成之后从 ApplicationContext 中获取 bean
		mqttServerTemplate = applicationContext.getBean(MqttServerTemplate.class);
	}
}
